package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exception.LyException;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.Category;
import com.leyou.item.entity.Sku;
import com.leyou.item.entity.Spu;
import com.leyou.item.entity.SpuDetail;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {

    @Autowired
    BrandService brandService;

    @Autowired
    CategoryService categoryService;

    @Autowired
    SpuDetailService detailService;

    @Autowired
    SkuService skuService;

    @Override
    public PageDTO<SpuDTO> listSpuByPage(Long bid, Long cid, Long spuid, Integer page, Integer rows, Boolean isSaleable) {
        Math.min(page, 100);
        rows = rows > 0 ? Math.max(5, rows) : this.count();
        IPage<Spu> info = new Page<>(page, rows);
        this.query()
                .eq(isSaleable != null, "saleable", isSaleable)
                .eq(bid != null, "brand_id", bid)
                .eq(cid != null, "cid3", cid)
                .eq(spuid != null, "id", spuid)
                .page(info);
        List<SpuDTO> spuDTOList = SpuDTO.convertEntityList(info.getRecords());
        spuDTOList.forEach(spuDTO -> {
            spuDTO.setBrandName(brandService.queryBrandById(spuDTO.getBrandId()).getName());
            List<Category> categoryList = categoryService.listByIds(spuDTO.getCategoryIds());
            spuDTO.setCategoryName(categoryList.stream().map(Category::getName).collect(Collectors.joining("/")));
        });
        return new PageDTO(info.getTotal(), info.getPages(), spuDTOList);
        /*.and(cid != null, spuQueryWrapper -> spuQueryWrapper
                        .eq(cid != null, "cid1", cid)
                        .or()
                        .eq(cid != null, "cid2", cid)
                        .or()
                        .eq(cid != null, "cid2", cid)
                )*/
        //categoryService.queryCategoryNamesById(spuDTO.getCid1(), spuDTO.getCid2(), spuDTO.getCid3()
            /*categoryService.query()
                    .eq("id",spuDTO.getCid1()).one().getName()+","+ categoryService.query()
                    .eq("id",spuDTO.getCid2()).one().getName() +","+categoryService.query()
                    .eq("id",spuDTO.getCid3()).one().getName()*/
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addSpu(SpuDTO spuDTO) {
        log.debug(spuDTO.toString());
        Spu spu = spuDTO.toEntity(Spu.class);
        spu.setSaleable(false);
        log.debug(spu.toString());
        if (!save(spu)) {
            throw new LyException(500, "添加商品失败");
        }
        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
        spuDetail.setSpuId(spu.getId());
        log.debug(spuDetail.toString());
        if (!detailService.save(spuDetail)) {
            throw new LyException(500, "添加商品详情失败");
        }
        List<SkuDTO> skuDTOList = spuDTO.getSkus();
        if (CollectionUtils.isEmpty(skuDTOList)) {
            throw new LyException(500, "至少需要一个sku,添加商品失败");
        }
        List<Sku> skuList = skuDTOList.stream().map(skuDTO -> {
            Sku sku = skuDTO.toEntity(Sku.class);
            sku.setSaleable(false);
            sku.setSpuId(spu.getId());
            return sku;
        }).collect(Collectors.toList());
        log.debug(skuList.toString());
        skuService.saveBatch(skuList);
    }

    @Override
    public SpuDetailDTO querySpuDetailBySpuId(Long spuId) {
        return new SpuDetailDTO(detailService.query().eq("spu_id", spuId).one());
    }

    @Override
    public SpuDTO getSpuById(Long id) {
        PageDTO<SpuDTO> spuDTOPageDTO = listSpuByPage(null, null, id, 1, 1, null);
        if (null != spuDTOPageDTO && !CollectionUtils.isEmpty(spuDTOPageDTO.getItems())) {
            SpuDTO spuDTO = spuDTOPageDTO.getItems().get(0);
            spuDTO.setSkus(skuService.querySkuListBySpuId(id));
            spuDTO.setSpuDetail(querySpuDetailBySpuId(id));
            return spuDTO;
        } else {
            throw new LyException(204, "该商品不存在");
        }
    }

    @Override
    public SpuDTO getSpuOnlyById(Long id) {
        PageDTO<SpuDTO> spuDTOPageDTO = listSpuByPage(null, null, id, 1, 1, null);
        if (null != spuDTOPageDTO && !CollectionUtils.isEmpty(spuDTOPageDTO.getItems())) {
            SpuDTO spuDTO = spuDTOPageDTO.getItems().get(0);
            return spuDTO;
        } else {
            throw new LyException(204, "该商品不存在");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateSaleable(Long id, Boolean saleable) {
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        Sku sku = new Sku();
        sku.setSaleable(saleable);
        skuService.update(sku, new UpdateWrapper<Sku>().eq("spu_id", id));
        if (!updateById(spu)) {
            throw new LyException(204, "该商品不存在,更新失败!");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateSpu(SpuDTO spuDTO) {
        Spu spu = spuDTO.toEntity(Spu.class);
        if (null != spu.getId()) {
            updateById(spu);
        }
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        if (null != spuDetailDTO) {
            detailService.updateById(spuDTO.toEntity(SpuDetail.class));
        }
        List<SkuDTO> skuDTOList = spuDTO.getSkus();
        List<Sku> toAdd = new ArrayList<>();
        List<Sku> toUpdate = new ArrayList<>();
        List<Sku> toDelete = new ArrayList<>();
        if (!CollectionUtils.isEmpty(skuDTOList)) {
            skuDTOList.forEach(skuDTO -> {
                Sku sku = skuDTO.toEntity(Sku.class);
                if (null == sku.getId()) {
                    toAdd.add(sku);
                } else if (null != sku.getSaleable()) {
                    toDelete.add(sku);
                } else {
                    toUpdate.add(sku);
                }
            });
        }
        if (!CollectionUtils.isEmpty(toAdd)) {
            skuService.saveBatch(toAdd);
        }
        if (!CollectionUtils.isEmpty(toDelete)) {
            skuService.removeByIds(toDelete.stream()
                    .map(Sku::getId)
                    .collect(Collectors.toList()));
        }
        if (!CollectionUtils.isEmpty(toUpdate)) {
            skuService.updateBatchById(toUpdate);
        }
        /*if (null != spuDTO) {
            Spu spu = spuDTO.toEntity(Spu.class);
            if (null != spu.getId()) {
                if (!updateById(spu)) {
                    throw new LyException(500, "修改商品失败");
                }
            }
            SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
            if (null != spuDetailDTO) {
                SpuDetail spuDetail = spuDetailDTO.toEntity(SpuDetail.class);
                if (!detailService.updateById(spuDetail)) {
                    throw new LyException(500, "修改商品详情失败");
                }
            }
            List<SkuDTO> skuDTOList = spuDTO.getSkus();
            if (!CollectionUtils.isEmpty(skuDTOList)) {
                List<Sku> skuList = skuDTOList.stream().map(skuDTO -> {
                    Sku sku = skuDTO.toEntity(Sku.class);
                    return sku;
                }).collect(Collectors.toList());
                skuService.updateBatchById(skuList);
            }
        }*/
    }
}